package com.android.love.web;

import android.os.Handler;
import android.os.Message;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 * 后台下载器
 */
public class DownloadRunnable implements Runnable {

	private static final int BUFFER_SIZE = 4096;

	private DownloadItem mParent;

	private boolean mAborted;

	/**
	 * 构造器.
	 * 
	 * @param parent
	 *            下载任务.
	 */
	public DownloadRunnable(DownloadItem parent) {
		mParent = parent;
		mAborted = false;
	}

	private Handler mHandler = new Handler() {

		public void handleMessage(Message msg) {
			mParent.onFinished();
		}
	};

	/**
	 * 根据下载地址推断文件名
	 * 
	 * @return 文件名
	 */
	private String getFileNameFromUrl() {
		String fileName = mParent.getUrl().substring(
				mParent.getUrl().lastIndexOf("/") + 1);

		int queryParamStart = fileName.indexOf("?");
		if (queryParamStart > 0) {
			fileName = fileName.substring(0, queryParamStart);
		}

		return fileName;
	}

	/**
	 * 在SD卡对应下载目录生成一个文件
	 * 
	 * @return
	 */
	private File getFile() {

		File downloadFolder = IOUtils.getDownloadFolder();

		if (downloadFolder != null) {

			return new File(downloadFolder, getFileNameFromUrl());

		} else {
			mParent.setErrorMessage("Unable to get download folder from SD Card.");
			return null;
		}
	}

	@Override
	public void run() {
		File downloadFile = getFile();

		if (downloadFile != null) {

			if (downloadFile.exists()) {
				downloadFile.delete();
			}

			BufferedInputStream bis = null;
			BufferedOutputStream bos = null;

			try {

				mParent.onStart();

				URL url = new URL(mParent.getUrl());
				URLConnection conn = url.openConnection();
				InputStream is = conn.getInputStream();
				int size = conn.getContentLength();
				String fileHeader = conn.getHeaderField("Content-Disposition");
				if (fileHeader != null) {
					fileHeader = fileHeader.toLowerCase();
					int index = fileHeader.indexOf("filename");
					if (index != -1) {
						String name = fileHeader.substring(
								index + "filename".length() + 1,
								fileHeader.length());

						name = name.replace("'", "").replace("\"", "");

						if (downloadFile != null) {
							downloadFile = new File(
									IOUtils.getDownloadFolder(), name);
							mParent.updateFileName(name);
						}
					}
				}

				double oldCompleted = 0;
				double completed = 0;

				bis = new BufferedInputStream(is);
				bos = new BufferedOutputStream(new FileOutputStream(
						downloadFile));

				boolean downLoading = true;
				byte[] buffer = new byte[BUFFER_SIZE];
				int downloaded = 0;
				int read;

				while ((downLoading) && (!mAborted)) {

					if ((size - downloaded < BUFFER_SIZE)
							&& (size - downloaded > 0)) {
						buffer = new byte[size - downloaded];
					}

					read = bis.read(buffer);

					if (read > 0) {
						bos.write(buffer, 0, read);
						downloaded += read;

						completed = ((downloaded * 100f) / size);

					} else {
						downLoading = false;
					}

					// Notify each 5% or more.
					if (oldCompleted + 5 < completed) {
						mParent.onProgress((int) completed);
						oldCompleted = completed;
					}
				}

			} catch (MalformedURLException mue) {
				mParent.setErrorMessage(mue.getMessage());
			} catch (IOException ioe) {
				mParent.setErrorMessage(ioe.getMessage());
			} finally {

				if (bis != null) {
					try {
						bis.close();
					} catch (IOException ioe) {
						mParent.setErrorMessage(ioe.getMessage());
					}
				}
				if (bos != null) {
					try {
						bos.close();
					} catch (IOException ioe) {
						mParent.setErrorMessage(ioe.getMessage());
					}
				}
			}

			if (mAborted) {
				if (downloadFile.exists()) {
					downloadFile.delete();
				}
			}

		}

		mHandler.sendEmptyMessage(0);
	}

	/**
	 * 中止下载.
	 */
	public void abort() {
		mAborted = true;
	}

}
